package com.zenithmind.disk.pojo.domain;

import com.fasterxml.jackson.annotation.JsonFormat;
import com.zenithmind.common.base.BaseEntity;
import com.zenithmind.disk.enums.ShareStatus;
import com.zenithmind.disk.enums.ShareVisibility;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.format.annotation.DateTimeFormat;

import java.time.LocalDateTime;

/**
 * 分享实体类
 * 遵循单一职责原则：专注于分享数据的表示和基本操作
 * 遵循开闭原则：通过枚举和方法封装，便于扩展
 */
@EqualsAndHashCode(callSuper = true)
@Data
@AllArgsConstructor
@NoArgsConstructor
@Schema(name = "管理用户分享的文件信息实体", description = "管理用户分享的文件信息实体")
public class Share extends BaseEntity {

    @Schema(description = "用户ID，关联users表")
    private String userId;

    @Schema(description = "文件ID，关联files表")
    private String fileId;

    @Schema(description = "分享码，用于访问分享链接")
    private String shareCode;

    @Schema(description = "分享链接")
    private String shareUrl;

    @Schema(description = "分享过期时间")
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
    @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    private LocalDateTime expireTime;

    @Schema(description = "访问次数")
    private Integer accessCount;

    @Schema(description = "是否公开，0表示私密，1表示公开")
    private Integer isPublic;

    @Schema(description = "私密分享时的访问密码")
    private String password;

    @Schema(description = "分享状态，1正常，其他值表示已失效等")
    private Integer status;

    // ==================== 业务方法 ====================

    /**
     * 获取分享状态枚举
     * @return 分享状态枚举
     */
    public ShareStatus getShareStatus() {
        return ShareStatus.fromCode(status);
    }

    /**
     * 设置分享状态
     * @param shareStatus 分享状态枚举
     */
    public void setShareStatus(ShareStatus shareStatus) {
        this.status = shareStatus != null ? shareStatus.getCode() : null;
    }

    /**
     * 获取分享可见性枚举
     * @return 分享可见性枚举
     */
    public ShareVisibility getShareVisibility() {
        return ShareVisibility.fromCode(isPublic);
    }

    /**
     * 设置分享可见性
     * @param visibility 分享可见性枚举
     */
    public void setShareVisibility(ShareVisibility visibility) {
        this.isPublic = visibility != null ? visibility.getCode() : null;
    }

    /**
     * 检查分享是否为公开分享
     * @return true如果是公开分享
     */
    public boolean isPublicShare() {
        return getShareVisibility().isPublic();
    }

    /**
     * 检查分享是否为私密分享
     * @return true如果是私密分享
     */
    public boolean isPrivateShare() {
        return getShareVisibility().isPrivate();
    }

    /**
     * 检查分享是否正常状态
     * @return true如果分享状态正常
     */
    public boolean isNormal() {
        return getShareStatus().isNormal();
    }

    /**
     * 检查分享是否已失效
     * @return true如果分享已失效
     */
    public boolean isInvalid() {
        return getShareStatus().isInvalid();
    }

    /**
     * 检查分享是否已过期
     * @return true如果分享已过期
     */
    public boolean isExpired() {
        return expireTime != null && LocalDateTime.now().isAfter(expireTime);
    }

    /**
     * 检查分享是否可访问
     * @return true如果分享可访问
     */
    public boolean isAccessible() {
        return isNormal() && !isExpired();
    }

    /**
     * 检查是否需要密码访问
     * @return true如果需要密码
     */
    public boolean requiresPassword() {
        return isPrivateShare() && StringUtils.isNotBlank(password);
    }

    /**
     * 验证访问密码
     * @param inputPassword 输入的密码
     * @return true如果密码正确
     */
    public boolean validatePassword(String inputPassword) {
        if (!requiresPassword()) {
            return true; // 公开分享或无密码分享
        }

        return StringUtils.equals(password, inputPassword);
    }

    /**
     * 增加访问次数
     */
    public void incrementAccessCount() {
        if (accessCount == null) {
            accessCount = 0;
        }
        accessCount++;
    }

    /**
     * 获取剩余有效时间（小时）
     * @return 剩余小时数，如果已过期返回0
     */
    public long getRemainingHours() {
        if (expireTime == null) {
            return Long.MAX_VALUE; // 永不过期
        }

        LocalDateTime now = LocalDateTime.now();
        if (now.isAfter(expireTime)) {
            return 0; // 已过期
        }

        return java.time.Duration.between(now, expireTime).toHours();
    }

    /**
     * 验证分享数据的完整性
     * @return true如果数据有效
     */
    public boolean isValid() {
        return StringUtils.isNotBlank(userId) &&
               StringUtils.isNotBlank(fileId) &&
               StringUtils.isNotBlank(shareCode) &&
               status != null &&
               isPublic != null &&
               accessCount != null && accessCount >= 0;
    }
}
